import axios from 'axios'
// 引入router
import router from '@/router'

// 引入store vuex数据
import store from '@/store'
// 引入qs模块
import qs from 'qs'

// 局部引入elelment 的message 的组件功能
import { Message } from 'element-ui'
// 存储因等待 Token 刷新⽽挂起的请求
let requests = []
// create 创建axios的实例自定义配置axios对象
const request = axios.create({
  // timeout: 2000
  // baseURL
  // headers
})

function getBaseURL (url) {
  if (url.startsWith('/boss')) {
    return 'http://eduboss.lagounews.com'
  } else {
    return 'http://edufront.lagounews.com'
  }
}
// axios 具有请求拦截器与响应拦截器，⽤于在请求与响应前进⾏提前处理。
request.interceptors.request.use(function (config) {
  // console.log(config)
  // 请拦截器参数 config 为本次请求的相关配置信息，这⾥通过 baseURL 来修改请求的基地址。
  // 判断config.url的前缀 来进行请求baseURL的设置
  config.baseURL = getBaseURL(config.url)
  // 统一鉴权接口
  // console.log(store.state)
  const { user } = store.state
  if (user && user.access_token) {
    config.headers.Authorization = user.access_token
  }
  return config
})

// 封装跳转函数
function redirectLogin () {
  // 跳转到登录页并且存储当前的fullPath
  router.push({
    name: 'login',
    query: {
      // 将本次路由的fullPath传给login currentRoute存储了路由信息的对象
      redirect: router.currentRoute.fullPath
    }
  })
}
// isRefreshing 标记 Token 的刷新状态
let isRefreshing = false

// Axios 官⽅⽂档：响应拦截器
// Add a response interceptor
request.interceptors.response.use(function (response) {
  // 状态码为2xx时的响应操作
  // console.log('响应成功了:', response)
  return response
}, function (error) {
  // console.log(error)
  if (error.response) {
    // 请求发送成功，响应接收完毕 但状态码失败
    // 1.判断失败的状态码的情况(主要处理401)
    const { status } = error.response
    let errorMessage = ''
    if (status === 400) {
      errorMessage = '请求参数错误'
      // 2.Token过期处理
    } else if (status === 401) {
      // errorMessage = 'Token无效' 处理Token无效问题
      // 1.无token信息
      if (!store.state.user) {
        redirectLogin()
        // 将本次的错误信息继续抛出,让接收响应数据的函数进行操作
        return Promise.reject(error)
      }
      // 判断是否已经存在正在刷新的token
      if (isRefreshing) {
        return requests.push(() => {
          request(error.config)
        })
      }
      // 发送刷新请求时，设置标记为 true
      isRefreshing = true
      // 2. 根据 refresh_token 请求新的 access_token
      return request({
        method: 'POST',
        url: '/front/user/refresh_token',
        data: qs.stringify({
          refreshtoken: store.state.user.refresh_token
        })
      }).then(res => {
        // console.log(res)
        // 如果刷新Token失败
        if (res.data.state !== 1) {
          // 清除已经⽆效的⽤户信息
          store.commit('setUser', null)
          redirectLogin()
          // 将本次的错误信息继续抛出,让接收响应数据的函数进行操作
          return Promise.reject(error)
        }
        // 如果刷新Token成功，将新的 access_token 更新到容器与本地存储中
        store.commit('setUser', res.data.content)
        // 这时再对之前报 401 的接⼝重新请求，同时 return
        requests.forEach(callback => callback())
        requests = []
        return request(error.config)
      }).catch(error => {
        // store.commit('setUser', null)
        // redirectLogin()
        // return Promise.reject(error)
        // console.log(error)
        console.dir(error)
      }).finally(() => {
        // 请求完毕，设置标记为 false
        isRefreshing = false
      })
    } else if (status === 403) {
      errorMessage = '没有权限，请联系管理员'
    } else if (status === 404) {
      errorMessage = '请求资源不存在'
    } else if (status >= 500) {
      errorMessage = '服务端错误，请联系管理员'
    }
    Message.error(errorMessage)
    // console.log(error.response.data)// Unauthorized
    // console.log(error.response.status)// status: 401
    // console.log(error.response.headers)// headers: {}
  } else if (error.request) {
    // 请求发送成功,但是未收到响应
    Message.error('请求超时,请重试')
  } else {
    // 意料之外的的错误
    Message.error(error.message)
  }
  // 将本次的错误信息继续抛出,让接收响应数据的函数进行操作
  return Promise.reject(error)
})
export default request
